package com.brillilab.starter.controller.aio.space;

import com.brillilab.common.constant.ResultEnum;
import com.brillilab.common.entity.ResponseVo;
import com.brillilab.common.exceptions.BrillilabException;
import com.brillilab.common.utils.MyBeanUtils;
import com.brillilab.domain.enums.common.IsDeleteEnum;
import com.brillilab.domain.enums.lab.LabMemberPowerEnum;
import com.brillilab.domain.enums.space.DeviceType;
import com.brillilab.domain.po.lab.LabDevice;
import com.brillilab.domain.po.space.Device;
import com.brillilab.domain.po.space.Room;
import com.brillilab.domain.vo.space.DeviceVo;
import com.brillilab.domain.vo.space.DeviceWithPanelsVo;
import com.brillilab.domain.vo.space.PositionInfo;
import com.brillilab.domain.vo.space.RoomWithDeviceList;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.service.core.lab.ILabDeviceService;
import com.brillilab.service.core.space.IDeviceService;
import com.brillilab.service.core.space.IRoomService;
import com.brillilab.service.core.system.IDictService;
import com.brillilab.service.logic.space.DeviceLogic;
import com.brillilab.service.logic.user.UsersLogic;
import com.brillilab.starter.aspect.AspectLog;
import com.brillilab.starter.constant.StarterConstant;
import com.brillilab.starter.handler.RequestPower;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wuzhiyu
 * @Title: Device
 * @ProjectName brill_lab
 * @Description: TODO
 * @date 2018/11/139:27
 */
@RestController
@RequestMapping("/api/spaceManage/device")
public class DeviceController {
    @Autowired
    private UsersLogic usersLogic;
    @Autowired
    private IDeviceService deviceService;
    @Autowired
    private IRoomService roomService;
    @Autowired
    private DeviceLogic deviceLogic;
    @Autowired
    private IDictService dictService;
    @Autowired
    private ILabDeviceService labDeviceService;

    @AspectLog
    @PostMapping("/add")
    @RequestPower(value = LabMemberPowerEnum.reagent)
    public ResponseVo add(@RequestBody List<DeviceWithPanelsVo> deviceList, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        if (StringUtils.isBlank(token)) {
            throw new BrillilabException(ResultEnum.USER_NOT_LOGIN);
        }
        Assert.notNull(deviceList, "数据为空");
        Assert.isTrue(deviceList.size() > 0, "数据为空");
        Long roomId = deviceList.get(0).getDevice().getRoomId();
        Map<Integer, String> indexMap = new HashMap<>();
        UserInfoVo info = usersLogic.getUserByToken(token);
        List<LabDevice> aioList =labDeviceService.selectList(info.getLabId(),null);
        Assert.isTrue(!CollectionUtils.isEmpty(aioList), "实验室无一体机");
        deviceList.forEach(o -> {
            indexMap.put(o.getDevice().getDeviceIndex(), "");
            Assert.isTrue(aioList.stream().filter(a->a.getState()==1&&a.getId().equals(o.getDevice().getAioDeviceId())).findAny().isPresent(), "无法绑定一体机");
            Assert.notNull(o.getDevice().getAioDeviceId(), "未绑定一体机");
            Assert.notNull(o.getDevice(), "device 为空");
            Assert.notNull(o.getPanelList(), "panel 为空");
            Assert.isTrue(o.getPanelList().size() > 0, "panel为空");
        });
        if (indexMap.keySet().size() != deviceList.size()) {
            throw new BrillilabException(ResultEnum.DATA_ALREADY_EXIST);
        }
        Assert.notNull(roomId, "RoomId为空");
        Room room = roomService.get(roomId);
        Assert.notNull(room, "房间不存在！");
        List<Device> dbDeviceList = deviceService.getLabAllDeviceList(room.getLabId(),null);
        deviceList.forEach(d -> {
            if (dbDeviceList.stream().filter(l -> l.getDeviceIndex() != null && l.getDeviceIndex().equals(d.getDevice().getDeviceIndex())).count() > 0) {
                throw new BrillilabException(ResultEnum.DATA_ALREADY_EXIST);
            }
        });
        if (!room.getLabId().equals(info.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        return ResponseVo.success(deviceLogic.add(deviceList, info.getLabId()));
    }

    @AspectLog
    @GetMapping("/edit")
    @RequestPower(value = LabMemberPowerEnum.reagent)
    public ResponseVo edit(Long deviceId, String remark, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        if (StringUtils.isBlank(token)) {
            throw new BrillilabException(ResultEnum.USER_NOT_LOGIN);
        }
        Assert.notNull(deviceId, "设备ID为空");
        UserInfoVo info = usersLogic.getUserByToken(token);
        Device device = deviceService.get(deviceId);
        Assert.notNull(device,"设备不存在");
        Assert.isTrue(IsDeleteEnum.NO.getValue().equals(device.getIsDelete()),"设备不存在");
        if (!device.getLabId().equals(info.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        device.setRemark(remark);
        return deviceService.update(device) ? ResponseVo.success() : ResponseVo.failure();
    }

    @AspectLog
    @DeleteMapping("/delete")
    @RequestPower(value = LabMemberPowerEnum.reagent)
    public ResponseVo delete(Long deviceId, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        if (StringUtils.isBlank(token)) {
            throw new BrillilabException(ResultEnum.USER_NOT_LOGIN);
        }
        Assert.notNull(deviceId, "设备ID为空");
        UserInfoVo info = usersLogic.getUserByToken(token);
        Device device = deviceService.get(deviceId);
        if (!device.getLabId().equals(info.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        return deviceLogic.delete(device) ? ResponseVo.success() : ResponseVo.failure();
    }

    @AspectLog
    @PutMapping("/update")
    @RequestPower(LabMemberPowerEnum.reagent)
    public ResponseVo update(@RequestBody List<PositionInfo> list, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        if (StringUtils.isBlank(token)) {
            throw new BrillilabException(ResultEnum.USER_NOT_LOGIN);
        }
        Assert.notNull(list, "设备列表为空");
        Assert.isTrue(list.size() > 0, "设备列表无数据！");
        UserInfoVo info = usersLogic.getUserByToken(token);
        list.forEach(o -> {
            Device device = deviceService.get(o.getId());
            Assert.notNull(device, "设备不存在");
            if (!device.getLabId().equals(info.getLabId())) {
                throw new BrillilabException(ResultEnum.USER_NOT_POWER);
            }
        });
        return deviceService.updatePosition(list) ? ResponseVo.success() : ResponseVo.failure();
    }


    @GetMapping("/deviceList")
    public ResponseVo deviceList(Long roomId, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        Assert.notNull(roomId, "参数roomId为空！");
        Room room = roomCheck(token, roomId);
        RoomWithDeviceList roomWithDeviceList = deviceLogic.deviceGroupList(room);
        return ResponseVo.success(roomWithDeviceList);
    }

    @GetMapping("/normalDeviceList")
    public ResponseVo normalDeviceList(Long roomId, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        roomCheck(token, roomId);
        List<Device> list = deviceService.list(roomId);
        List<DeviceVo> voList = new ArrayList<>();
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        for (Device d : list) {
            if (d.getDeviceType().equals(DeviceType.DEVICE.getCode())) {
                DeviceVo v = new DeviceVo();
                MyBeanUtils.copyProperties(d, v);
                v.setZoneName(zoneMap.get(v.getZone()));
                voList.add(v);
            }
        }
        return ResponseVo.success(voList);
    }

    @GetMapping("/indexList")
    public ResponseVo indexList(@RequestHeader(value = StarterConstant.TOKEN) String token) {
        UserInfoVo user = usersLogic.getUserByToken(token);
        List<Device> list = deviceService.getLabAllDeviceList(user.getLabId(),null);
        List<Integer> indexList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            indexList = list.stream().map(Device::getDeviceIndex).filter(i -> i != null && (!i.equals(0))).distinct().collect(Collectors.toList());
        }
        return ResponseVo.success(indexList);
    }
    
    @AspectLog
    @GetMapping("/aioUpdate")
    @RequestPower(value = LabMemberPowerEnum.reagent)
    public ResponseVo aioUpdate(Long id,String name,@RequestHeader(value = StarterConstant.TOKEN) String token){
        Device device = deviceService.get(id);
        Assert.notNull(device,"设备不存在");
        Assert.isTrue(!StringUtils.isEmpty(name),"名称不能为空");
        UserInfoVo info = usersLogic.getUserByToken(token);
        Assert.isTrue(info.getLabId().equals(device.getLabId()),"设备不存在");
        Assert.isTrue(!device.getDeviceType().equals(DeviceType.MACHINE), "非法操作");
        return   deviceLogic.updateAio(device,name)?ResponseVo.success():ResponseVo.failure();
    }
    private Room roomCheck(String token, Long roomId) {
        if (StringUtils.isBlank(token)) {
            throw new BrillilabException(ResultEnum.USER_NOT_LOGIN);
        }
        Assert.notNull(roomId, "设备ID为空");
        Room room = roomService.get(roomId);
        Assert.notNull(room, "设备不存在");
        UserInfoVo info = usersLogic.getUserByToken(token);
        if (!room.getLabId().equals(info.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        return room;
    }
    
    /**
     * 根据一体机设备编号获取实设备
     * @param deviceNo
     * @return
     */
    @GetMapping("/listByAioDeviceNo")
    public ResponseVo listByAioDeviceNo(@RequestParam String deviceNo) {
        List<Device> list = deviceService.listByAioDeviceNo(deviceNo);
        return ResponseVo.success(list);
    }
    
    /**
     * 获取实验室所有设备
     * @param deviceNo
     * @return
     */
    @GetMapping("/allDeviceList")
    public ResponseVo allDeviceList(@RequestParam String deviceNo) {
    	LabDevice labDevice = labDeviceService.selectByNo(deviceNo);
    	Assert.notNull(labDevice, "一体机设备不存在");
        List<Device> list = deviceService.getLabAllDeviceList(labDevice.getLabId(),null);
        return ResponseVo.success(list);
    }
}
